package cn.lijiguo.concurrency.part1.ch06;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * WrongWayVolatileCantStop
 * 演示使用 volatile 关键字的局限性：part 2 陷入阻塞时，volatile 是无法停止线程的
 * 此示例中，生产者的生产速度很快，消费者的消费速度慢，所以堵塞队列满了以后，生产者会阻塞，等待消费者消费
 * @author lijiguo
 * @date 2020/1/6 13:32
 */
public class WrongWayVolatileCantStop {

    public static void main(String[] args) throws InterruptedException {
        ArrayBlockingQueue<Integer> storage = new ArrayBlockingQueue<>(10);

        Producer producer = new Producer(storage);
        Thread producerThread = new Thread(producer, "producer");
        producerThread.start();

        Thread.sleep(5000);

        Consumer consumer = new Consumer(storage);
        while (consumer.needMoreNums()) {
            System.out.println(consumer.storage.take() + " 被消费了...");
            Thread.sleep(100);
        }
        System.out.println("消费者不需要更多数据了...");

        // 生产者停止生产
        producer.canceled = true;
        System.out.println(producer.canceled);
    }
}

/**
 * 生产者
 */
class Producer implements Runnable {

    volatile boolean canceled = false;

    BlockingQueue<Integer> storage;

    public Producer(BlockingQueue<Integer> storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        int num = 0;
        try {
            while(num <= 10000 && !canceled) {
                if (num % 100 == 0) {
                    storage.put(num);
                    System.out.println(num + " 是 100 的倍数，被放到仓库中了");
                }

                num++;

                Thread.sleep(1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("生产者停止运行");
        }
    }
}

/**
 * 消费者
 */
class Consumer {

    BlockingQueue<Integer> storage;

    public Consumer(BlockingQueue<Integer> storage) {
        this.storage = storage;
    }

    public boolean needMoreNums() {
        return Math.random() > 0.95;
    }
}
